import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:grint/data/chat_data.dart';
import 'package:grint/entity/chat_message.dart';
import 'package:grint/utils/whisper.dart';

/// 聊天状态
class ChatState {
  final List<ChatConversation> conversations;
  final List<ChatMessage> currentMessages;
  final ChatConversation? currentConversation;
  final bool isLoading;
  final bool isSending;
  final String? errorMessage;

  const ChatState({
    this.conversations = const [],
    this.currentMessages = const [],
    this.currentConversation,
    this.isLoading = false,
    this.isSending = false,
    this.errorMessage,
  });

  ChatState copyWith({
    List<ChatConversation>? conversations,
    List<ChatMessage>? currentMessages,
    ChatConversation? currentConversation,
    bool? isLoading,
    bool? isSending,
    String? errorMessage,
    bool clearError = false,
    bool clearConversation = false,
  }) {
    return ChatState(
      conversations: conversations ?? this.conversations,
      currentMessages: currentMessages ?? this.currentMessages,
      currentConversation:
          clearConversation
              ? null
              : (currentConversation ?? this.currentConversation),
      isLoading: isLoading ?? this.isLoading,
      isSending: isSending ?? this.isSending,
      errorMessage: clearError ? null : (errorMessage ?? this.errorMessage),
    );
  }
}

/// 聊天管理 Cubit
class ChatCubit extends Cubit<ChatState> {
  final ChatData _chatData = ChatData();

  ChatCubit() : super(const ChatState());

  Future<void> loadUserConversations(String userId) async {
    emit(state.copyWith(isLoading: true, clearError: true));

    try {
      final conversations = await _chatData.getUserConversations(userId);
      emit(state.copyWith(conversations: conversations, isLoading: false));
    } catch (e) {
      emit(
        state.copyWith(
          isLoading: false,
          errorMessage: 'Failed to load conversations: $e',
        ),
      );
    }
  }

  Future<void> startConversationWithUser(
    String currentUserId,
    String otherUserId,
  ) async {
    emit(state.copyWith(isLoading: true, clearError: true));

    try {
      ChatConversation? conversation = await _chatData
          .getConversationBetweenUsers(currentUserId, otherUserId);

      if (conversation == null) {
        conversation = await _chatData.createConversation(
          currentUserId,
          otherUserId,
        );
      }

      final messages = await _chatData.getConversationMessages(conversation.id);

      await _chatData.markMessagesAsRead(conversation.id, currentUserId);

      emit(
        state.copyWith(
          currentConversation: conversation,
          currentMessages: messages,
          isLoading: false,
        ),
      );
    } catch (e) {
      emit(
        state.copyWith(
          isLoading: false,
          errorMessage: 'Failed to start conversation: $e',
        ),
      );
    }
  }

  Future<void> sendMessage({
    required String content,
    required String senderId,
    MessageType type = MessageType.text,
  }) async {
    if (state.currentConversation == null) {
      Whisper.hiss('No active conversation');
      return;
    }

    if (content.trim().isEmpty) {
      Whisper.hiss('Message cannot be empty');
      return;
    }

    emit(state.copyWith(isSending: true, clearError: true));

    try {
      final receiverId = state.currentConversation!.getOtherUserId(senderId);

      final message = await _chatData.sendMessage(
        conversationId: state.currentConversation!.id,
        senderId: senderId,
        receiverId: receiverId,
        content: content,
        type: type,
      );

      final updatedMessages = [...state.currentMessages, message];

      emit(state.copyWith(currentMessages: updatedMessages, isSending: false));

      await loadUserConversations(senderId);
    } catch (e) {
      emit(
        state.copyWith(
          isSending: false,
          errorMessage: 'Failed to send message: $e',
        ),
      );
      Whisper.hiss('Failed to send message');
    }
  }

  Future<void> refreshCurrentMessages() async {
    if (state.currentConversation == null) return;

    try {
      final messages = await _chatData.getConversationMessages(
        state.currentConversation!.id,
      );

      emit(state.copyWith(currentMessages: messages));
    } catch (e) {
      emit(state.copyWith(errorMessage: 'Failed to refresh messages: $e'));
    }
  }

  Future<void> markCurrentMessagesAsRead(String userId) async {
    if (state.currentConversation == null) return;

    try {
      await _chatData.markMessagesAsRead(state.currentConversation!.id, userId);
      await refreshCurrentMessages();
    } catch (e) {}
  }

  Future<void> deleteConversation(String conversationId, String userId) async {
    try {
      await _chatData.deleteConversation(conversationId, userId);

      if (state.currentConversation?.id == conversationId) {
        emit(state.copyWith(clearConversation: true, currentMessages: []));
      }

      await loadUserConversations(userId);
    } catch (e) {
      emit(state.copyWith(errorMessage: 'Failed to delete conversation: $e'));
      Whisper.hiss('Failed to delete conversation');
    }
  }

  void clearError() {
    emit(state.copyWith(clearError: true));
  }

  void clearCurrentConversation() {
    emit(state.copyWith(clearConversation: true, currentMessages: []));
  }

  int getTotalUnreadCount() {
    return state.conversations.fold(0, (sum, conv) => sum + conv.unreadCount);
  }

  bool hasUnreadMessages() {
    return getTotalUnreadCount() > 0;
  }
}
